package ejb;

import java.util.ArrayList;
import java.util.List;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;

import util.XMLReader;
import bean.ArtPendiente;
import bean.ArtPendiente.EstadoEnvio;
import bean.Articulo;
import bean.PendienteFabricacion;
import ejbInterfaces.AdministradorSolDistBeanLocal;
import generated.SolDist;
import generated.SolDist.Envio;
import generated.SolDist.Envio.Articulos;

@Stateless
public class AdministradorSolDistBean implements AdministradorSolDistBeanLocal {

	@PersistenceContext(unitName = "MyDatabase")
	EntityManager em;
	static Logger logger = Logger.getLogger(AdministradorSolDistBean.class);

	public void ejbCreate() {
	}

	public AdministradorSolDistBean() {

	}

	public List<ArtPendiente> leerSolDist() {
		List<Envio> enviosTotal = new ArrayList<Envio>();
		List<ArtPendiente> listaTotal = null;
		try {
			listaTotal = new ArrayList<ArtPendiente>();
			// Obtengo datos del XML
			SolDist solDist = XMLReader.getInstance().leerSolDist();
			enviosTotal = solDist.getEnvio();
			int numSolDist = solDist.getNumSolDist();
			// Recorro lista de envios y voy armando un hashmap para devolver
			// los
			// articulos con sus cantidades y stocks
			for (Envio e : enviosTotal) {
				List<Articulos> tempList = e.getArticulos();
				for (Articulos a : tempList) {
					// transformo a lista de ArtPendiente
					ArtPendiente articulo = new ArtPendiente();
					articulo.setIdTienda(e.getIdTienda());
					articulo.setReferencia(a.getRef());
					articulo.setCantidad(a.getCant());
					articulo.setNumSolDist(numSolDist);
					listaTotal.add(articulo);
				}
			}
		} catch (Exception e) {
			logger.log(Level.ERROR, "Error leyendosolicitud de distribucion", e);
			e.printStackTrace();
		}
		return listaTotal;
	}

	// Actualiza stock de articulos
	public void updateStockArtEnviar(List<ArtPendiente> listaTotal) {
		try {
			for (ArtPendiente entry : listaTotal) {

				Query q = em
						.createQuery(" from Articulo where referencia = ?1");
				q.setParameter(1, entry.getReferencia());
				List<Articulo> result = q.getResultList();
				Articulo art = null;
				if(result.size() != 0){
					art = result.get(0);
				}
				if (art != null) {
					int dif = art.getStock() - entry.getCantidad();
					//Me alcanza para enviar todo lo pedido
					if (dif >= 0) {
						art.setStock(dif);
						em.merge(art);
						agregarPendientes(entry, EstadoEnvio.LISTO);
					} else if (dif < 0){
						int resto = entry.getCantidad() - art.getStock();
						//no tengo nada de stock
						if(art.getStock() == 0){
							art.setStock(0);
							em.merge(art);
							agregarPendientes(entry, EstadoEnvio.PENDIENTE);
							agregarFabricacion(entry, resto);
						}else{//tengo algo de stock
							entry.setCantidad(resto);
							agregarPendientes(entry, EstadoEnvio.PENDIENTE);
							entry.setCantidad(art.getStock());
//							entry.setEstado(EstadoEnvio.LISTO);
							agregarPendientes(entry, EstadoEnvio.LISTO);
							art.setStock(0);
							em.merge(art);
							agregarFabricacion(entry, resto);
						}
					} else {
						logger.log(Level.ERROR, "Objeto inexistente. Referencia: "+ entry.getReferencia());
						System.out.println("Objeto inexistente. Referencia: "+ entry.getReferencia());
					}
				}

			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void agregarFabricacion(ArtPendiente entry, int resto) {
		PendienteFabricacion artF = null;
		Query q = em
				.createQuery("from PendienteFabricacion where referencia = :ref");
		q.setParameter("ref", entry.getReferencia());
		List<PendienteFabricacion> result = q.getResultList();
		if (result.size() != 0) {
			artF = result.get(0);
		}

		if (artF == null) {
			artF = new PendienteFabricacion();
			// busco la descripcion
			Query q2 = em.createQuery("from Articulo where referencia = :ref");
			q2.setParameter("ref", entry.getReferencia());
			List<Articulo> result2 = q2.getResultList();
			if (result2.size() != 0){
				Articulo art = result2.get(0);
				// actualizo datos del artF
				artF.setReferencia(entry.getReferencia());
				artF.setCantPendiente(resto);
				artF.setDescripcion(art.getDescripcion());
				em.persist(artF);
			}

		} else {
			artF.setCantPendiente(artF.getCantPendiente()+ entry.getCantidad());
			em.merge(artF);
		}
	}

	private void agregarPendientes(ArtPendiente art, EstadoEnvio estado) {
		// en xml puedo tener mismo articulo que debe ser enviado a
		// diferentes tiendas
		ArtPendiente artP = null;
		Query q = em.createQuery("from ArtPendiente where referencia = :ref and idTienda = :idTienda and estado = :estado and numSolDist = :numSolDist");
		q.setParameter("ref", art.getReferencia()).setParameter("idTienda",	art.getIdTienda()).setParameter("estado", estado).setParameter("numSolDist", art.getNumSolDist());
		List<ArtPendiente> result = q.getResultList();
		if (result.size() != 0) {
			artP = result.get(0);
		}
		if (artP == null) {
			artP = new ArtPendiente();
			artP.setCantidad(art.getCantidad());
			artP.setIdTienda(art.getIdTienda());
			artP.setReferencia(art.getReferencia());
			artP.setEstado(estado);
			artP.setNumSolDist(art.getNumSolDist());
			em.persist(artP);
		} else {
			artP.setCantidad(artP.getCantidad() + art.getCantidad());
			em.merge(artP);
		}

	}

	public List<ArtPendiente> obtenerArticulosAEnviar(
			List<ArtPendiente> listaTotal) {
		List<ArtPendiente> articulosAEnviar = new ArrayList<ArtPendiente>();
		try {
			for (ArtPendiente entry : listaTotal) {

				Query q = em
						.createQuery(" from Articulo where referencia = ?1");
				q.setParameter(1, entry.getReferencia());
				List<Articulo> result = q.getResultList();
				Articulo art  = null;
				if (result.size() != 0) {
					art = result.get(0);
				}
				
				if (art != null) {
					int dif = art.getStock() - entry.getCantidad();
					if (dif >= 0) {
						articulosAEnviar.add(entry);
					} else if (art.getStock() - entry.getCantidad() < 0) {
						int stockReal = art.getStock();
						entry.setCantidad(stockReal);
						if (stockReal != 0) {
							articulosAEnviar.add(entry);
						}
					} else {
						System.out.println("Objeto inexistente. Referencia: "
								+ entry.getReferencia());
					}
				}

			}
		} catch (Exception e) {
			logger.log(Level.ERROR, "Error obteniendo articulos a enviar desde soldist", e );
			e.printStackTrace();
		}
		return articulosAEnviar;
	}

	public List<ArtPendiente> obtenerArticulosPendientes(
			List<ArtPendiente> listaTotal) {
		List<ArtPendiente> articulosPendientes = new ArrayList<ArtPendiente>();
		try {
			for (ArtPendiente entry : listaTotal) {

				Query q = em
						.createQuery(" from Articulo where referencia = ?1");
				q.setParameter(1, entry.getReferencia());
				List<Articulo> result = q.getResultList();
				
				Articulo art  = null;
				if (result.size() != 0) {
					art = result.get(0);
				}
				
				if (art != null) {
					int dif = art.getStock() - entry.getCantidad();
					if (art.getStock() - entry.getCantidad() < 0) {
						// me pidieron 100 y tengo 20
						int resto = entry.getCantidad() - art.getStock();
						entry.setCantidad(resto);
						articulosPendientes.add(entry);
					} else {
						System.out.println("Objeto inexistente. Referencia: "
								+ entry.getReferencia());
					}
				}

			}
		} catch (Exception e) {
			e.printStackTrace();
			logger.log(Level.ERROR, "Error obteniendo articulos pendientes desde soldist", e );
		}
		return articulosPendientes;
	}

}
